using GLib;
//using Gee;
using Rob;
using Gypsy;
namespace FreeDesktop.Gypsy
{
    [DBus (name = "org.freedesktop.Gypsy.Device")]
    public interface Device : GLib.Object {
        public abstract bool get_connection_status() throws DBus.Error;
        public abstract int get_fix_status() throws DBus.Error;
        public abstract void start() throws DBus.Error;
        public abstract void stop() throws DBus.Error;
        public signal void connection_status_changed();
        public signal void fix_status_changed();
    }
    [DBus (name = "org.freedesktop.Gypsy.Position")]
    public interface Position : GLib.Object 
    {
        public abstract void get_position(out int fields, out int tstamp, out double lat, out double lon, out double alt) throws DBus.Error;

        public signal void position_changed();
    }

}

namespace Rob
{
    namespace Rules
    {
    	public GLib.List<Rob.Rules.GPS> gpslist;
    	public class GPS: Rob.Rules.Rule
    	{
            public static string BUS_NAME = "org.freedesktop.gypsy";
            public static string DEV_OBJ_PATH = "/org/freedesktop/gypsy/device";
            public static string POS_OBJ_PATH = "/org/freedesktop/gypsy/position";
            //private string _name;
            //private string _title;
            private int _interval;
            private double _latitude;
            private double _longitude;
            private int _distance;
            private Rob.Rules.GPSHelper gps;

            private DBus.Connection conn;
            private FreeDesktop.Gypsy.Position position;
            private FreeDesktop.Gypsy.Device device;
            private string path;
            construct
            {
                _title = "";
                _name = "";
                _distance = 0;
                _longitude = 0.0;
                _latitude = 0.0;
                _type="gps";
            }
            public GPS()
            {
            }
            ~GPS()
            {
                    stdout.printf("Dtor\n");
                    this.device.stop();
            }	

    
            public int interval
            {
                    get{ return _interval;}
                    set{ _interval = value; }
            }
            public string title
            {
                    get{return _title;}
                    set{_title = value;}
            }
            public string name
            {
                    get{return _name;}
                    set{_name = value;}
            }	
            public double latitude
            {
                    get{ return _latitude;}
                    set{ _latitude = value;}
            }
            public double longitude
            {
                    get{ return _longitude; }
                    set{ longitude = value; }
            }
            public int distance
            {
                    get{return _distance; }
                    set{_distance = value; }
            }


            public /*override*/ bool check()
            {
                    return false;
            }
            public /*override*/ bool load(GLib.KeyFile kf, string name)
            {
                    try
                    {
                            this._name = name;
                            this._title = kf.get_string(name, "title");	
                            this.interval = kf.get_integer(name, "interval" );
                            this.latitude = kf.get_double( name, "latitude" );
                            this.longitude = kf.get_double( name , "longitude" );
                            this.distance = kf.get_integer( name , "distance" );
                    }

                    catch( GLib.KeyFileError kfe)
                    {
                            return false;
                    }
                    return true;
            }
            public /*override*/ bool save(ref GLib.KeyFile kf)
            {
                    base.save(ref kf);
                    kf.set_string( _name, "title", _title );
                    
                    kf.set_integer( _name, "interval", _interval );
                    kf.set_double( _name, "latitude", _latitude );
                    kf.set_double( _name, "longitude", _longitude );
                    kf.set_integer( _name, "distance", _distance );
                    return true;	
            }
            public /*override*/ void run()
            {
                try
                {
                    conn = DBus.Bus.get( BusType.SYSTEM );
                    device = ( FreeDesktop.Gypsy.Device ) conn.get_object( BUS_NAME, DEV_OBJ_PATH );
                    position = ( FreeDesktop.Gypsy.Position ) conn.get_object( BUS_NAME, POS_OBJ_PATH );
                    device.start();
                    int fields =0, tstamp =0;
                    double alt = 0.0;
                    position.get_position( out fields, out tstamp, out _latitude, out _longitude, out alt );
                    //deprecated syntax in 0.7
                    position.position_changed += this.pos_changed;
                    debug( "%i: fields: %i lat: %lf lon: %lf",tstamp,fields, _latitude, _longitude  );
                }
                catch (GLib.Error e)
                {
                    debug( "gps get object: %s", e.message );
                }
            }
            public void check_distance(double longitude, double latitude)
            {
                    //6371000.785 is the median earthradius
                    this.fulfilled=  GLib.Math.sqrt( GLib.Math.pow( 
                                    (this._latitude - latitude )  * 40000000.0 / 360.0, 2 ) + 
                                    GLib.Math.pow( (this._longitude - longitude)/360.0 * 40000000.0, 2 ) ) < 
                                    this._distance  ? true: false;
            }
            private void   pos_changed (GPSHelper obj, int fields_set, int timestamp, double latitude, double longitude, double altitude)
            {
                    if((fields_set & Gypsy.PositionFields.LATITUDE) != 0 && ( fields_set & Gypsy.PositionFields.LATITUDE ) != 0 )
                            this.check_distance( longitude, latitude );
                    else
                            GLib.warning("%i GPS position incorrect\n", timestamp);
            }
    }

}
